#!/usr/bin/env python
# -*- coding: utf-8 -*-

import matplotlib.pyplot as plt
from pylab import mpl
from datetime import datetime, timedelta
from django.core.exceptions import ValidationError
from django.db.utils import DataError
from django.db.models import Q
from web.util.dto_util import DtoUtil
from web.util.datetime_util import DatetimeUtil
from web.constants.k_line_period_type import KLinePeriodType
from web.constants.datetime_format import DatetimeFormat
from web.manager.log_manager import LogManager
from web.models.commodity_future_date_data import CommodityFutureDateData
from web.service.base_service import BaseService
from web.config.create_date_picture_config import CreateDatePictureConfig
from web.config.create_week_picture_config import CreateWeekPictureConfig
from web.config.commodity_future_date_data_config import CommodityFutureDateDataConfig
from web.config.robot8_config import Robot8Config
from web.util.math_util import MathUtil

Logger = LogManager.get_logger(__name__)

"""
CommodityFutureDateData的service类
"""


class CommodityFutureDateDataService(BaseService):

    def add_oracle_column_comment(self):
        """
        为表commodity_future_date_data添加注释
        """

        Logger.info('为表commodity_future_date_data添加注释')

        self.commodity_future_date_data_dao.add_oracle_column_comment()

    def save_commodity_future_date_data_list(self, commodity_future_data_list):
        """
        保存CommodityFutureDateData类型对象列表
        """

        Logger.info('保存CommodityFutureDateData类型对象列表')

        for commodity_future_data_dto in commodity_future_data_list:
            commodity_future_date_data = DtoUtil.commodity_future_data_dto_to_commodity_future_date_data(
                commodity_future_data_dto)
            # try:
            if isinstance(commodity_future_date_data.close_price, str) or isinstance(
                    commodity_future_date_data.highest_price, str) or isinstance(
                commodity_future_date_data.open_price, str) or isinstance(
                commodity_future_date_data.lowest_price, str) or isinstance(
                commodity_future_date_data.price_change, str) or isinstance(
                commodity_future_date_data.rising_and_falling_amount, str) or isinstance(
                commodity_future_date_data.volume, str):
                Logger.warn('期货[%s]在交易日[%s]没有数据', commodity_future_date_data.code,
                            datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
                continue
            else:
                commodity_future_date_data.transaction_date = datetime.now()

                commodity_future_date_data_list = CommodityFutureDateData.objects.filter(
                    Q(code=commodity_future_date_data.code) & Q(
                        transaction_date=commodity_future_date_data.transaction_date)).count()
                commodity_future_date_data.save()

    ########################################### 全量计算数据 ########################################

    def write_date_basic_data(self):
        """
        计算日线级别全部last_close_price、rising_and_falling_amount和price_change字段
        """

        Logger.info("计算日线级别全部last_close_price、rising_and_falling_amount和price_change字段")

        self.commodity_future_date_data_dao.write_date_basic_data()

    def write_date_all_ma(self):
        """
        计算日线级别全部MA数据
        """

        Logger.info("计算日线级别全部MA数据")

        self.commodity_future_date_data_dao.write_date_all_ma()

    def write_date_all_macd(self):
        """
        计算日线级别全部MACD数据
        """

        Logger.info("计算日线级别全部MACD数据")

        self.commodity_future_date_data_dao.write_date_all_macd()

    def write_date_all_kd(self):
        """
        计算日线级别全部KD数据
        """

        Logger.info("计算日线级别全部KD数据")

        self.commodity_future_date_data_dao.write_date_all_kd()

    def write_date_all_boll(self):
        """
        计算日线级别全部boll数据
        """

        Logger.info("计算日线级别全部boll数据")

        self.commodity_future_date_data_dao.write_date_all_boll()

    def write_date_all_hei_kin_ashi(self):
        """
        计算日线级别全部hei_kin_ashi数据
        """

        Logger.info("计算日线级别全部hei_kin_ashi数据")

        self.commodity_future_date_data_dao.write_date_all_hei_kin_ashi()

    def write_date_all_bias(self):
        """
        计算日线级别全部bias数据
        """

        Logger.info("计算日线级别全部bias数据")

        self.commodity_future_date_data_dao.write_date_all_bias()

    def write_date_all_variance(self):
        """
        计算日线级别全部variance数据
        """

        Logger.info("计算日线级别全部variance数据")

        self.commodity_future_date_data_dao.write_date_all_variance()

    def write_date_unite_relative_price_index(self):
        """
        计算日线级别全部unite_relative_price_index数据
        """

        Logger.info("计算日线级别全部unite_relative_price_index数据")

        self.commodity_future_date_data_dao.write_date_unite_relative_price_index()

    ########################################### 增量计算数据 ########################################

    def write_date_basic_data_by_date(self):
        """
        根据日期，计算日线级别某一个交易日的last_close_price、rising_and_falling_amount和price_change字段
        """

        Logger.info("根据日期，计算日线级别交易日[%s]的last_close_price、rising_and_falling_amount和price_change字段",
                    CommodityFutureDateDataConfig.Commodity_Future_Date_Data_Basic_Data_By_Date)

        self.commodity_future_date_data_dao.write_date_basic_data_by_date(
            CommodityFutureDateDataConfig.Commodity_Future_Date_Data_Basic_Data_By_Date)

    def write_date_unite_relative_price_index_by_date(self):
        """
        根据日期，计算日线级别某一个交易日的unite_relative_price_index数据
        """

        Logger.info("根据日期，计算日线级别交易日[%s]的unite_relative_price_index数据",
                    CommodityFutureDateDataConfig.Commodity_Future_Date_Data_Unite_Relative_Price_Index_By_Date)

        self.commodity_future_date_data_dao.write_date_unite_relative_price_index_by_date(
            CommodityFutureDateDataConfig.Commodity_Future_Date_Data_Unite_Relative_Price_Index_By_Date)

    def write_date_ma_by_date(self):
        """
        根据日期，计算日线级别某一个交易日的MA数据
        """

        Logger.info("根据日期，计算日线级别交易日[%s]的MA数据",
                    CommodityFutureDateDataConfig.Commodity_Future_Date_Data_Ma_By_Date)

        self.commodity_future_date_data_dao.write_date_ma_by_date(
            CommodityFutureDateDataConfig.Commodity_Future_Date_Data_Ma_By_Date)

    def write_date_macd_by_date(self):
        """
        根据日期，计算日线级别某一个交易日的MACD数据
        """

        Logger.info("根据日期，计算日线级别交易日[%s]的MACD数据",
                    CommodityFutureDateDataConfig.Commodity_Future_Date_Data_Macd_By_Date)

        self.commodity_future_date_data_dao.write_date_macd_by_date(
            CommodityFutureDateDataConfig.Commodity_Future_Date_Data_Macd_By_Date)

    def write_date_kd_by_date(self):
        """
        根据日期，计算日线级别某一个交易日的KD数据
        """

        Logger.info("根据日期，计算日线级别交易日[%s]的KD数据",
                    CommodityFutureDateDataConfig.Commodity_Future_Date_Data_Kd_By_Date)

        self.commodity_future_date_data_dao.write_date_kd_by_date(
            CommodityFutureDateDataConfig.Commodity_Future_Date_Data_Kd_By_Date)

    def write_date_boll_by_date(self):
        """
        根据日期，计算日线级别某一个交易日的boll数据
        """

        Logger.info("根据日期，计算日线级别交易日[%s]的boll数据",
                    CommodityFutureDateDataConfig.Commodity_Future_Date_Data_Boll_By_Date)

        self.commodity_future_date_data_dao.write_date_boll_by_date(
            CommodityFutureDateDataConfig.Commodity_Future_Date_Data_Boll_By_Date)

    def write_date_hei_kin_ashi_by_date(self):
        """
        根据日期，计算日线级别某一个交易日的hei kin ashi数据
        """

        Logger.info("根据日期，计算日线级别交易日[%s]的hei kin ashi数据",
                    CommodityFutureDateDataConfig.Commodity_Future_Date_Data_Hei_Kin_Ashi_By_Date)

        self.commodity_future_date_data_dao.write_date_hei_kin_ashi_by_date(
            CommodityFutureDateDataConfig.Commodity_Future_Date_Data_Hei_Kin_Ashi_By_Date)

    def write_date_variance_by_date(self):
        """
        根据日期，计算日线级别某一个交易日的variance数据
        """

        Logger.info("根据日期，计算日线级别交易日[%s]的variance数据",
                    CommodityFutureDateDataConfig.Commodity_Future_Date_Data_Variance_By_Date)

        self.commodity_future_date_data_dao.write_date_variance_by_date(
            CommodityFutureDateDataConfig.Commodity_Future_Date_Data_Hei_Kin_Ashi_By_Date)

    def write_date_bias_by_date(self):
        """
        根据日期，计算日线级别某一个交易日的BOLL数据
        """

        Logger.info("根据日期，计算日线级别交易日[%s]的BIAS数据",
                    CommodityFutureDateDataConfig.Commodity_Future_Date_Data_Bias_By_Date)

        self.commodity_future_date_data_dao.write_date_bias_by_date(
            CommodityFutureDateDataConfig.Commodity_Future_Date_Data_Bias_By_Date)

    #################################################### 查询 ################################################

    def find_max_and_min_transaction_date_by_code(self, code):
        """
        根据code，查询最大的和最小的transaction_date
        """

        max_transaction_date, min_transaction_date = self.commodity_future_date_data_dao.find_max_and_min_transaction_date_by_code(code)
        return max_transaction_date, min_transaction_date

    #################################################### 创建图片 ################################################
    def create_four_strategy_gold_cross_rate_picture(self):
        """
        创建图片：根据四种算法，计算各自金叉百分比，生成折线图
        """

        Logger.info("创建图片：根据四种算法，计算各自金叉百分比，生成折线图，开始时间[%s]，结束时间[%s]",
                    CreateDatePictureConfig.Four_Strategy_Gold_Cross_Rate_Picture_Begin_Date,
                    CreateDatePictureConfig.Four_Strategy_Gold_Cross_Rate_Picture_End_Date)

        # 根据开始日期和结束日期，计算每一天，四种算法金叉的比率
        four_strategy_gold_cross_rate_tuple = self.commodity_future_date_data_dao.find_four_strategy_gold_cross_rate_between_group_by_order_by_transaction_date(
            CreateDatePictureConfig.Four_Strategy_Gold_Cross_Rate_Picture_Begin_Date,
            CreateDatePictureConfig.Four_Strategy_Gold_Cross_Rate_Picture_End_Date)

        transaction_date_array = list()
        macd_gold_cross_rate_array = list()
        close_price_gold_cross_ma5_rate_array = list()
        hei_kin_ashi_up_rate_array = list()
        kd_gold_cross_rate_array = list()
        for item in four_strategy_gold_cross_rate_tuple:
            transaction_date_array.append(item[0])
            macd_gold_cross_rate_array.append(item[1])
            close_price_gold_cross_ma5_rate_array.append(item[2])
            hei_kin_ashi_up_rate_array.append(item[3])
            kd_gold_cross_rate_array.append(item[4])

        # 创建一个新的图表
        fig, ax = plt.subplots(figsize=(18, 8))

        # 关闭交互模式
        plt.ioff()

        mpl.rcParams["font.sans-serif"] = ["SimHei"]

        # 创建折线图
        ax.plot(transaction_date_array, macd_gold_cross_rate_array, label='macd金叉', linewidth=0.5, marker='o',
                color='red')
        ax.plot(transaction_date_array, close_price_gold_cross_ma5_rate_array, label='close_price金叉ma5',
                linewidth=0.5,
                marker='o', color='blue')
        ax.plot(transaction_date_array, hei_kin_ashi_up_rate_array, label='hei kin ashi上升趋势', linewidth=0.5,
                marker='o',
                color='green')
        ax.plot(transaction_date_array, kd_gold_cross_rate_array, label='kd金叉', linewidth=0.5, marker='o',
                color='black')
        plt.legend()
        plt.title('根据四种算法，计算各自金叉百分比，生成折线图')
        plt.xlabel('时间')
        plt.ylabel('百分比')

        # 分辨率
        plt.rcParams['savefig.dpi'] = 300

        # 显示图例
        # plt.legend()

        # 保存图表
        plt.savefig(CreateDatePictureConfig.Four_Strategy_Gold_Cross_Rate_Picture_Save_Path)

        # 显示图表
        # plt.show()

        # 关闭图表
        plt.close()

    def create_average_four_strategy_gold_cross_rate_and_its_and_ma5_picture(self):
        """
        创建图片：根据四种算法，计算各自金叉百分比，再计算平均值，这是第一条线。计算这个数据的MA5，这是第二条线。两条线一起生成折线图
        """

        Logger.info(
            "创建图片：根据四种算法，计算各自金叉百分比，再计算平均值，这是第一条线。计算这个数据的MA5，这是第二条线。两条线一起生成折线图，开始时间[%s]，结束时间[%s]",
            CreateDatePictureConfig.Average_Four_Strategy_Gold_Cross_Rate_Picture_And_Its_And_Ma5_Begin_Date,
            CreateDatePictureConfig.Average_Four_Strategy_Gold_Cross_Rate_Picture_And_Its_And_Ma5_End_Date)

        # 根据开始日期和结束日期，计算每一天，四种算法金叉的比率的平均值
        average_four_strategy_gold_cross_rate_tuple = self.commodity_future_date_data_dao.find_average_four_strategy_gold_cross_rate_between_group_by_order_by_transaction_date(
            CreateDatePictureConfig.Average_Four_Strategy_Gold_Cross_Rate_Picture_And_Its_And_Ma5_Begin_Date,
            CreateDatePictureConfig.Average_Four_Strategy_Gold_Cross_Rate_Picture_And_Its_And_Ma5_End_Date)

        transaction_date_array = list()
        average_four_strategy_gold_cross_rate_list = list()
        average_four_strategy_gold_cross_rate_ma5_list = list()
        for transaction_date, average_rate in average_four_strategy_gold_cross_rate_tuple:
            transaction_date_array.append(transaction_date)
            average_four_strategy_gold_cross_rate_list.append(average_rate)

            # 根据开始日期和结束日期，计算每一天，四种算法金叉的比率的平均值的ma5
            five_date_datetime = self.commodity_future_date_data_dao.find_backward_between_n_date(
                DatetimeUtil.datetime_to_str(transaction_date, DatetimeFormat.Date_Format_With_Line), 5)
            average_four_strategy_gold_cross_rate_tuple_latest_five = self.commodity_future_date_data_dao.find_average_four_strategy_gold_cross_rate_between_group_by_order_by_transaction_date(
                DatetimeUtil.datetime_to_str(five_date_datetime, DatetimeFormat.Date_Format_With_Line),
                DatetimeUtil.datetime_to_str(transaction_date, DatetimeFormat.Date_Format_With_Line))
            sum: float = 0
            for _transaction_date, _average_rate in average_four_strategy_gold_cross_rate_tuple_latest_five:
                sum += _average_rate
            average_four_strategy_gold_cross_rate_ma5_list.append(sum / 5)

        # 创建一个新的图表
        fig, ax = plt.subplots(figsize=(18, 8))

        # 关闭交互模式
        plt.ioff()

        mpl.rcParams["font.sans-serif"] = ["SimHei"]

        # 创建折线图
        ax.plot(transaction_date_array, average_four_strategy_gold_cross_rate_list, label='平均金叉率', linewidth=0.5,
                marker='o',
                color='red')
        ax.plot(transaction_date_array, average_four_strategy_gold_cross_rate_ma5_list, label='平均金叉率的ma5',
                linewidth=0.5,
                marker='o', color='blue')
        plt.legend()
        plt.title(
            '根据四种算法，计算各自金叉百分比，再计算平均值，这是第一条线。计算这个数据的MA5，这是第二条线。两条线一起生成折线图')
        plt.xlabel('时间')
        plt.ylabel('百分比')

        # 分辨率
        plt.rcParams['savefig.dpi'] = 300

        # 显示图例
        # plt.legend()

        # 保存图表
        plt.savefig(CreateDatePictureConfig.Average_Four_Strategy_Gold_Cross_Rate_Picture_And_Its_And_Ma5_Save_Path)

        # 显示图表
        # plt.show()

        # 关闭图表
        plt.close()

    def create_price_change_up_percentage_picture(self):
        """
        创建图片：日线级别上涨的期货的百分比
        """

        Logger.info("创建图片：日线级别上涨的期货的百分比，时间从[%s]至[%s]",
                    CreateDatePictureConfig.Price_Change_Up_Percentage_Begin_Date,
                    CreateDatePictureConfig.Price_Change_Up_Percentage_End_Date)

        price_change_up_percentage_tuple = self.commodity_future_date_data_dao.find_date_price_change_up_percentage_group_by_transaction_date(
            CreateDatePictureConfig.Price_Change_Up_Percentage_Begin_Date,
            CreateDatePictureConfig.Price_Change_Up_Percentage_End_Date)

        transaction_date_array = list()
        price_change_up_percentage_array = list()
        middle_line_array = list()
        average_price_change_5_backward_array = list()
        average_price_change_10_backward_array = list()
        average_price_change_20_backward_array = list()
        for price_change_up_percentage in price_change_up_percentage_tuple:
            _transaction_date = DatetimeUtil.datetime_to_str(price_change_up_percentage[0],
                                                             DatetimeFormat.Date_Format_With_Line)

            average_price_change_5_backward = self.commodity_future_date_data_dao.average_price_change_up_percentage_by_current_transaction_date(
                _transaction_date, 5)
            average_price_change_10_backward = self.commodity_future_date_data_dao.average_price_change_up_percentage_by_current_transaction_date(
                _transaction_date, 10)
            average_price_change_20_backward = self.commodity_future_date_data_dao.average_price_change_up_percentage_by_current_transaction_date(
                _transaction_date, 20)

            transaction_date_array.append(_transaction_date)
            price_change_up_percentage_array.append(price_change_up_percentage[1])
            average_price_change_5_backward_array.append(average_price_change_5_backward)
            average_price_change_10_backward_array.append(average_price_change_10_backward)
            average_price_change_20_backward_array.append(average_price_change_20_backward)
            middle_line_array.append(50)

        # 创建一个新的图表
        fig, ax = plt.subplots(figsize=(18, 8))

        # 关闭交互模式
        plt.ioff()

        mpl.rcParams["font.sans-serif"] = ["SimHei"]

        # 创建折线图
        ax.plot(transaction_date_array, middle_line_array, label='中轴线', linewidth=0.5,
                marker='o',
                color='red')
        ax.plot(transaction_date_array, price_change_up_percentage_array, label='上涨的期货的百分比',
                linewidth=0.5,
                marker='o', color='black')
        ax.plot(transaction_date_array, average_price_change_5_backward_array, label='上涨的期货的百分比（5日均线）',
                linewidth=0.5,
                marker='o', color='blue')
        ax.plot(transaction_date_array, average_price_change_10_backward_array, label='上涨的期货的百分比（10日均线）',
                linewidth=0.5,
                marker='o', color='green')
        ax.plot(transaction_date_array, average_price_change_20_backward_array, label='上涨的期货的百分比（20日均线）',
                linewidth=0.5,
                marker='o', color='brown')
        plt.legend()
        plt.title('日线级别上涨的期货的百分比及其均线')
        plt.xlabel('时间')
        plt.ylabel('百分比')

        # 分辨率
        plt.rcParams['savefig.dpi'] = 300

        # 显示图例
        # plt.legend()

        # 保存图表
        plt.savefig(CreateDatePictureConfig.Price_Change_Up_Percentage_Save_Path)

        # 显示图表
        # plt.show()

        # 关闭图表
        plt.close()

    def create_bull_short_line_picture(self):
        """
        创建图片：每个期货的牛熊线图
        """

        Logger.info("创建图片：每个期货的牛熊线图，时间从[%s]至[%s]", CreateDatePictureConfig.Bull_Short_Line_Begin_Date,
                    CreateDatePictureConfig.Bull_Short_Line_End_Date)

        begin_date = DatetimeUtil.str_to_datetime(CreateDatePictureConfig.Bull_Short_Line_Begin_Date,
                                                  DatetimeFormat.Date_Format)
        end_date = DatetimeUtil.str_to_datetime(CreateDatePictureConfig.Bull_Short_Line_End_Date,
                                                DatetimeFormat.Date_Format)

        # 所有期货的code
        code_tuple = CommodityFutureDateData.objects.filter(transaction_date__range=[begin_date, end_date]).values_list(
            'code', flat=True).distinct()
        if code_tuple != None and len(code_tuple) != 0:
            for code in code_tuple:
                # 每个期货的数据
                commodity_future_date_data_list = CommodityFutureDateData.objects.all().filter(
                    Q(transaction_date__range=[begin_date, end_date]) &
                    Q(code=code)).order_by('transaction_date')

                transaction_date_array = list()
                close_price_array = list()
                bull_short_line_array = list()
                if commodity_future_date_data_list != None and len(commodity_future_date_data_list) != 0:
                    for commodity_future_date_data in commodity_future_date_data_list:
                        # 牛熊线
                        bull_short_line = None
                        if commodity_future_date_data.ma250 != None and commodity_future_date_data.bias250 <= Robot8Config.Bias_Threshold_Top \
                                and commodity_future_date_data.bias250 >= Robot8Config.Bias_Threshold_Bottom:
                            bull_short_line = commodity_future_date_data.ma250
                        elif commodity_future_date_data.ma120 != None and commodity_future_date_data.bias120 <= Robot8Config.Bias_Threshold_Top \
                                and commodity_future_date_data.bias120 >= Robot8Config.Bias_Threshold_Bottom:
                            bull_short_line = commodity_future_date_data.ma120
                        elif commodity_future_date_data.ma60 != None and commodity_future_date_data.bias60 <= Robot8Config.Bias_Threshold_Top \
                                and commodity_future_date_data.bias60 >= Robot8Config.Bias_Threshold_Bottom:
                            bull_short_line = commodity_future_date_data.ma60
                        elif commodity_future_date_data.ma20 != None and commodity_future_date_data.bias20 <= Robot8Config.Bias_Threshold_Top \
                                and commodity_future_date_data.bias20 >= Robot8Config.Bias_Threshold_Bottom:
                            bull_short_line = commodity_future_date_data.ma20
                        elif commodity_future_date_data.ma10 != None and commodity_future_date_data.bias10 <= Robot8Config.Bias_Threshold_Top \
                                and commodity_future_date_data.bias10 >= Robot8Config.Bias_Threshold_Bottom:
                            bull_short_line = commodity_future_date_data.ma10
                        elif commodity_future_date_data.ma5 != None and commodity_future_date_data.bias5 <= Robot8Config.Bias_Threshold_Top \
                                and commodity_future_date_data.bias5 >= Robot8Config.Bias_Threshold_Bottom:
                            bull_short_line = commodity_future_date_data.ma5
                        elif bull_short_line == None:
                            # 如果最后任何bias指标都无法确定哪一根均线可以作为牛熊线的话，则将前一个交易日的收盘价作为牛熊线。注意：现在数据库中last_close_price字段没有空值
                            bull_short_line = commodity_future_date_data.last_close_price
                        transaction_date_array.append(commodity_future_date_data.transaction_date)
                        close_price_array.append(commodity_future_date_data.close_price)
                        bull_short_line_array.append(bull_short_line)

                    # 创建一个新的图表
                    fig, ax = plt.subplots(figsize=(18, 8))

                    # 关闭交互模式
                    plt.ioff()

                    mpl.rcParams["font.sans-serif"] = ["SimHei"]
                    mpl.rcParams['axes.unicode_minus'] = False

                    # 创建折线图
                    ax.plot(transaction_date_array, close_price_array, label='收盘价', linewidth=0.5,
                            marker='o',
                            color='black')
                    ax.plot(transaction_date_array, bull_short_line_array, label='牛熊线',
                            linewidth=0.5,
                            marker='o', color='red')
                    plt.legend()
                    plt.title('每个期货的牛熊线图')
                    plt.xlabel('时间')
                    plt.ylabel('收盘价')

                    # 分辨率
                    plt.rcParams['savefig.dpi'] = 300

                    # 显示图例
                    # plt.legend()

                    # 保存图表
                    plt.savefig(CreateDatePictureConfig.Bull_Short_Line_Save_Path.replace('${code}',
                                                                                          commodity_future_date_data.code))

                    # 显示图表
                    # plt.show()

                    # 关闭图表
                    plt.close()

    def create_average_kd_picture(self):
        """
        创建图片：日线级别平均KD图
        """

        Logger.info("创建图片：日线级别平均KD图，开始时间[%s]，结束时间[%s]",
                    CreateDatePictureConfig.Average_KD_Begin_Date,
                    CreateDatePictureConfig.Average_KD_End_Date)

        # 根据开始日期和结束日期，查询所有交易日
        transaction_date_tuple = self.commodity_future_date_data_dao.find_distinct_transaction_date_between_transaction_date_order_by_transaction_date(
            CreateDatePictureConfig.Average_KD_Begin_Date,
            CreateDatePictureConfig.Average_KD_End_Date)

        transaction_date_array = list()
        k_array = list()
        d_array = list()
        for transaction_date in transaction_date_tuple:
            # 根据日期，计算每个交易日的平均kd
            average_kd_tuple = self.commodity_future_date_data_dao.find_average_kd_order_by_transaction_date_asc(
                transaction_date[0])
            transaction_date_array.append(average_kd_tuple[0])
            k_array.append(average_kd_tuple[1])
            d_array.append(average_kd_tuple[2])

        # 创建一个新的图表
        fig, ax = plt.subplots(figsize=(18, 8))

        # 关闭交互模式
        plt.ioff()

        mpl.rcParams["font.sans-serif"] = ["SimHei"]

        # 创建折线图
        ax.plot(transaction_date_array, k_array, label='平均K', linewidth=0.5, marker='o', color='red')
        ax.plot(transaction_date_array, d_array, label='平均D', linewidth=0.5, marker='o', color='blue')
        plt.legend()
        plt.title('日线级别KD图')
        plt.xlabel('时间')
        plt.ylabel('KD')

        # 分辨率
        plt.rcParams['savefig.dpi'] = 300

        # 显示图例
        # plt.legend()

        # 保存图表
        plt.savefig(CreateDatePictureConfig.Average_KD_Save_Path)

        # 显示图表
        # plt.show()

        # 关闭图表
        plt.close()

    def create_average_boll_picture(self):
        """
        创建图片：日线级别平均BOLL图
        """

        Logger.info("创建图片：日线级别平均BOLL图，开始时间[%s]，结束时间[%s]",
                    CreateDatePictureConfig.Average_Boll_Begin_Date,
                    CreateDatePictureConfig.Average_Boll_End_Date)

        # 根据开始日期和结束日期，查询所有交易日
        transaction_date_tuple = self.commodity_future_date_data_dao.find_distinct_transaction_date_between_transaction_date_order_by_transaction_date(
            CreateDatePictureConfig.Average_Boll_Begin_Date,
            CreateDatePictureConfig.Average_Boll_End_Date)

        transaction_date_array = list()
        close_price_array = list()
        up_array = list()
        mb_array = list()
        dn_array = list()
        for transaction_date in transaction_date_tuple:
            # 根据日期，计算每个交易日的平均kd
            average_boll_tuple = self.commodity_future_date_data_dao.find_average_boll_order_by_transaction_date_asc(
                transaction_date[0])
            transaction_date_array.append(average_boll_tuple[0])
            close_price_array.append(average_boll_tuple[1])
            up_array.append(average_boll_tuple[2])
            mb_array.append(average_boll_tuple[3])
            dn_array.append(average_boll_tuple[4])

        # 创建一个新的图表
        fig, ax = plt.subplots(figsize=(18, 8))

        # 关闭交互模式
        plt.ioff()

        mpl.rcParams["font.sans-serif"] = ["SimHei"]

        # 创建折线图
        ax.plot(transaction_date_array, close_price_array, label='平均close_price', linewidth=0.5, marker='o',
                color='black')
        ax.plot(transaction_date_array, up_array, label='平均up', linewidth=0.5, marker='o', color='red')
        ax.plot(transaction_date_array, mb_array, label='平均mb', linewidth=0.5, marker='o', color='blue')
        ax.plot(transaction_date_array, dn_array, label='平均dn', linewidth=0.5, marker='o', color='green')
        plt.legend()
        plt.title('日线级别平均BOLL图')
        plt.xlabel('时间')
        plt.ylabel('BOLL')

        # 分辨率
        plt.rcParams['savefig.dpi'] = 300

        # 显示图例
        # plt.legend()

        # 保存图表
        plt.savefig(CreateDatePictureConfig.Average_Boll_Save_Path)

        # 显示图表
        # plt.show()

        # 关闭图表
        plt.close()

    def create_bond_and_stock_correlation_picture(self):
        """
        创建图片：十债、国债指数、国债ETF、上证指数和平均股价之间相关性的折线图
        """

        Logger.info("创建图片：十债、国债指数、国债ETF、上证指数和平均股价之间相关性的折线图，开始时间[%s]，结束时间[%s]",
                    CreateDatePictureConfig.Bond_And_Stock_Correlation_Begin_Date,
                    CreateDatePictureConfig.Bond_And_Stock_Correlation_End_Date)

        # 根据开始日期和结束日期，查询所有交易日期
        transaction_date_tuple = self.commodity_future_date_data_dao.find_distinct_transaction_date_between_transaction_date_order_by_transaction_date(
            CreateDatePictureConfig.Bond_And_Stock_Correlation_Begin_Date,
            CreateDatePictureConfig.Bond_And_Stock_Correlation_End_Date)

        # 根据开始日期和结束日期，查询所有十债收盘价
        ten_year_bond_close_price_tuple = self.commodity_future_date_data_dao.find_date_and_close_price_by_code_between_transaction_date_order_by_transaction_date_asc(
            "T", CreateDatePictureConfig.Bond_And_Stock_Correlation_Begin_Date,
            CreateDatePictureConfig.Bond_And_Stock_Correlation_End_Date)

        # 根据开始日期和结束日期，查询所有国债指数收盘价
        bond_index_close_price_list = self.baostock_bond_index_dao.find_date_and_close_price_by_code_between_date_order_by_date("000012",
            CreateDatePictureConfig.Bond_And_Stock_Correlation_Begin_Date, CreateDatePictureConfig.Bond_And_Stock_Correlation_End_Date)

        # 根据开始日期和结束日期，查询所有国债ETF收盘价
        bond_etf_close_price_list = self.etf_transaction_data_dao.find_date_and_close_price_by_code_between_date_order_by_date_asc("511020",
            CreateDatePictureConfig.Bond_And_Stock_Correlation_Begin_Date, CreateDatePictureConfig.Bond_And_Stock_Correlation_End_Date)

        # 根据开始日期和结束日期，查询所有上证指数收盘价
        sh_index_close_price_tuple = self.stock_index_dao.find_date_and_close_price_by_code_between_date_order_by_date_asc("000001",
            CreateDatePictureConfig.Bond_And_Stock_Correlation_Begin_Date, CreateDatePictureConfig.Bond_And_Stock_Correlation_End_Date)

        # 根据开始日期和结束日期，查询所有平均股价收盘价
        average_stock_close_price_tuple = self.stock_transaction_data_all_dao.find_date_and_average_close_price_between_date_order_by_date_asc(
            CreateDatePictureConfig.Bond_And_Stock_Correlation_Begin_Date, CreateDatePictureConfig.Bond_And_Stock_Correlation_End_Date)

        # 交易日期数组
        transaction_date_array = list()
        # 十债收盘价数组
        ten_year_bond_close_price_array = list()
        # 国债指数收盘价数组
        bond_index_close_price_array = list()
        # 国债ETF收盘价数组
        bond_etf_close_price_array = list()
        # 上证指数收盘价数组
        sh_index_close_price_array = list()
        # 平均股价收盘价数组
        average_stock_close_price_array = list()

        ten_year_bond_close_price_index = 0
        last_ten_year_bond_close_price = 0
        bond_index_close_price_index = 0
        last_bond_index_close_price = 0
        bond_etf_close_price_index = 0
        last_bond_etf_close_price = 0
        sh_index_close_price_index = 0
        last_sh_index_close_price = 0
        average_stock_close_price_index = 0
        last_average_stock_close_price = 0
        for index, transaction_date in enumerate(transaction_date_tuple):
            transaction_date_array.append(transaction_date[0])

            if index + 1 > len(ten_year_bond_close_price_tuple):
                ten_year_bond_close_price_array.append(last_ten_year_bond_close_price)
            elif transaction_date[0] == ten_year_bond_close_price_tuple[ten_year_bond_close_price_index][0]:
                ten_year_bond_close_price_array.append(ten_year_bond_close_price_tuple[ten_year_bond_close_price_index][1])
                last_ten_year_bond_close_price = ten_year_bond_close_price_tuple[ten_year_bond_close_price_index][1]
                ten_year_bond_close_price_index = ten_year_bond_close_price_index + 1
            else:
                ten_year_bond_close_price_array.append(last_ten_year_bond_close_price)

            if index + 1 > len(bond_index_close_price_list):
                bond_index_close_price_array.append(last_bond_index_close_price)
            elif transaction_date[0] == bond_index_close_price_list[bond_index_close_price_index][0]:
                bond_index_close_price_array.append( bond_index_close_price_list[bond_index_close_price_index][1])
                last_bond_index_close_price = bond_index_close_price_list[bond_index_close_price_index][1]
                bond_index_close_price_index = bond_index_close_price_index + 1
            else:
                bond_index_close_price_array.append(last_bond_index_close_price)

            if index + 1 > len(bond_etf_close_price_list):
                bond_etf_close_price_array.append(last_bond_etf_close_price)
            elif transaction_date[0] == bond_etf_close_price_list[bond_etf_close_price_index][0]:
                bond_etf_close_price_array.append(bond_etf_close_price_list[bond_etf_close_price_index][1])
                last_bond_etf_close_price = bond_etf_close_price_list[bond_etf_close_price_index][1]
                bond_etf_close_price_index = bond_etf_close_price_index + 1
            else:
                bond_etf_close_price_array.append(last_bond_etf_close_price)

            if index + 1 > len(sh_index_close_price_tuple):
                sh_index_close_price_array.append(last_sh_index_close_price)
            elif transaction_date[0] == sh_index_close_price_tuple[sh_index_close_price_index][0]:
                sh_index_close_price_array.append(sh_index_close_price_tuple[sh_index_close_price_index][1])
                last_sh_index_close_price = sh_index_close_price_tuple[sh_index_close_price_index][1]
                sh_index_close_price_index = sh_index_close_price_index + 1
            else:
                sh_index_close_price_array.append(last_sh_index_close_price)

            if index + 1 > len(average_stock_close_price_tuple):
                average_stock_close_price_array.append(last_average_stock_close_price)
            elif transaction_date[0] == average_stock_close_price_tuple[average_stock_close_price_index][0]:
                average_stock_close_price_array.append(average_stock_close_price_tuple[average_stock_close_price_index][1])
                last_average_stock_close_price = average_stock_close_price_tuple[average_stock_close_price_index][1]
                average_stock_close_price_index = average_stock_close_price_index + 1
            else:
                average_stock_close_price_array.append(last_average_stock_close_price)

        # 归一化
        ten_year_bond_close_price_array = MathUtil.normalize(ten_year_bond_close_price_array)[0]
        bond_index_close_price_array = MathUtil.normalize(bond_index_close_price_array)[0]
        bond_etf_close_price_array = MathUtil.normalize(bond_etf_close_price_array)[0]
        sh_index_close_price_array = MathUtil.normalize(sh_index_close_price_array)[0]
        average_stock_close_price_array = MathUtil.normalize(average_stock_close_price_array)[0]

        # 创建一个新的图表
        fig, ax = plt.subplots(figsize=(18, 8))

        # 关闭交互模式
        plt.ioff()

        mpl.rcParams["font.sans-serif"] = ["SimHei"]

        # 创建折线图
        ax.plot(transaction_date_array, ten_year_bond_close_price_array, label='十债收盘价', linewidth=0.5, marker='o',
                color='green')
        ax.plot(transaction_date_array, bond_index_close_price_array, label='国债指数收盘价', linewidth=0.5, marker='o',
                color='purple')
        ax.plot(transaction_date_array, bond_etf_close_price_array, label='国债ETF收盘价', linewidth=0.5, marker='o',
                color='blue')
        ax.plot(transaction_date_array, sh_index_close_price_array, label='上证指数收盘价', linewidth=0.5, marker='o',
                color='black')
        ax.plot(transaction_date_array, average_stock_close_price_array, label='平均股价收盘价', linewidth=0.5,
                marker='o', color='red')
        plt.legend()
        plt.title('十债、国债指数、国债ETF、上证指数和平均股价之间相关性的折线图')
        plt.xlabel('时间')
        plt.ylabel('收盘价')

        # 分辨率
        plt.rcParams['savefig.dpi'] = 300

        # 显示图例
        # plt.legend()

        # 保存图表
        plt.savefig(CreateDatePictureConfig.Bond_And_Stock_Correlation_Save_Path)

        # 显示图表
        # plt.show()

        # 关闭图表
        plt.close()
